//
//  YQNetworking.m
//  YQNetworking
//
//  Created by yingqiu huang on 2017/2/10.
//  Copyright © 2017年 yingqiu huang. All rights reserved.
//

#import "YQNetworking.h"
#import "AFNetworking.h"
#import "AFNetworkActivityIndicatorManager.h"
#import "YQNetworking+RequestManager.h"
#import "YQCacheManager.h"

#import "LoginViewController.h"

#define YQ_ERROR_IMFORMATION @"网络出现错误，请检查网络连接"

#define YQ_ERROR [NSError errorWithDomain:@"com.hyq.YQNetworking.ErrorDomain" code:-999 userInfo:@{ NSLocalizedDescriptionKey:YQ_ERROR_IMFORMATION}]

static NSMutableArray   *requestTasksPool;

static NSDictionary     *headers;

static YQNetworkStatus  networkStatus;

static NSTimeInterval   requestTimeout = 20.f;

@implementation YQNetworking
#pragma mark - manager
+ (AFHTTPSessionManager *)manager {
    [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
    
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    //默认解析模式
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    
    //配置请求序列化
    AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];
    
    [serializer setRemovesKeysWithNullValues:YES];
    
    manager.requestSerializer.stringEncoding = NSUTF8StringEncoding;
    
    manager.requestSerializer.timeoutInterval = requestTimeout;
    
    for (NSString *key in headers.allKeys) {
        if (headers[key] != nil) {
            [manager.requestSerializer setValue:headers[key] forHTTPHeaderField:key];
        }
    }
    
    //配置响应序列化
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithArray:@[@"application/json",
                                                                              @"text/html",
                                                                              @"text/json",
                                                                              @"text/plain",
                                                                              @"text/javascript",
                                                                              @"text/xml",
                                                                              @"image/*",
                                                                              @"application/octet-stream",
                                                                              @"application/zip"]];
    
    [self checkNetworkStatus];
    
    //每次网络请求的时候，检查此时磁盘中的缓存大小，阈值默认是40MB，如果超过阈值，则清理LRU缓存,同时也会清理过期缓存，缓存默认SSL是7天，磁盘缓存的大小和SSL的设置可以通过该方法[YQCacheManager shareManager] setCacheTime: diskCapacity:]设置
    [[YQCacheManager shareManager] clearLRUCache];
    
    return manager;
}

#pragma mark - 检查网络
+ (void)checkNetworkStatus {
    AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
    
    [manager startMonitoring];
    
    [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        
        switch (status) {
            case AFNetworkReachabilityStatusNotReachable:
                networkStatus = YQNetworkStatusNotReachable;
                break;
            case AFNetworkReachabilityStatusUnknown:
                networkStatus = YQNetworkStatusUnknown;
                break;
            case AFNetworkReachabilityStatusReachableViaWWAN:
                networkStatus = YQNetworkStatusReachableViaWWAN;
                break;
            case AFNetworkReachabilityStatusReachableViaWiFi:
                networkStatus = YQNetworkStatusReachableViaWiFi;
                break;
            default:
                networkStatus = YQNetworkStatusUnknown;
                break;
        }
        
    }];
}

+ (NSMutableArray *)allTasks {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (requestTasksPool == nil) requestTasksPool = [NSMutableArray array];
    });
    
    return requestTasksPool;
}

#pragma mark - get
+ (YQURLSessionTask *)getWithUrl:(NSString *)url
                  refreshRequest:(BOOL)refresh
                           cache:(BOOL)cache
                          params:(NSDictionary *)params
                   progressBlock:(YQGetProgress)progressBlock
                    successBlock:(YQResponseSuccessBlock)successBlock
                       failBlock:(YQResponseFailBlock)failBlock {
    //将session拷贝到堆中，block内部才可以获取得到session
    __block YQURLSessionTask *session = nil;
    
    AFHTTPSessionManager *manager = [self manager];
    
    if (networkStatus == YQNetworkStatusNotReachable) {
        if (failBlock) failBlock(YQ_ERROR);
        return session;
    }
    
    id responseObj = [[YQCacheManager shareManager] getCacheResponseObjectWithRequestUrl:url params:params];
    
    if (responseObj && cache) {
        if (successBlock) successBlock(responseObj);
    }
    
    if (![url containsString:@"http"]) {
        
        url = [NSString stringWithFormat:@"%@%@",BASEURL,url];
    }
   
    session = [manager GET:url parameters:params headers:@{} progress:^(NSProgress * _Nonnull downloadProgress) {
        if (progressBlock) {
            progressBlock(downloadProgress.completedUnitCount, downloadProgress.totalUnitCount);
        }
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"{\n parameters: %@ url:   %@ \n responseObject:  %@ \n}",(params==nil?@"没有参数":params),url,responseObject);
        if (successBlock) {
            successBlock(responseObject); }
        
        if (cache) {
            [[YQCacheManager shareManager] cacheResponseObject:responseObject requestUrl:url params:params];
        }
        if ([[self allTasks] containsObject:session]) {
            [[self allTasks] removeObject:session];
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failBlock) failBlock(error);
        [[self allTasks] removeObject:session];
    }];
    if ([self haveSameRequestInTasksPool:session] && !refresh) {
        //取消新请求
        [session cancel];
        return session;
    }else {
        //无论是否有旧请求，先执行取消旧请求，反正都需要刷新请求
        YQURLSessionTask *oldTask = [self cancleSameRequestInTasksPool:session];
        if (oldTask) [[self allTasks] removeObject:oldTask];
        if (session) [[self allTasks] addObject:session];
        [session resume];
        return session;
    }
}
+ (YQURLSessionTask *)getWithUrl:(NSString *)url
                          params:(NSDictionary *)params
             reloginRefreshBlock:(YQReloginRefreshBlock)reloginRefreshBlock
                    successBlock:(YQResponseSuccessBlock)successBlock
                       failBlock:(YQResponseFailBlock)failBlock {
    //将session拷贝到堆中，block内部才可以获取得到session
    __block YQURLSessionTask *session = nil;
    
    AFHTTPSessionManager *manager = [self manager];
    
    if (networkStatus == YQNetworkStatusNotReachable) {
        if (failBlock) failBlock(YQ_ERROR);
        return session;
    }
    
    
    if (![url containsString:@"http"]) {
        
        url = [NSString stringWithFormat:@"%@%@",BASEURL,url];
    }
    
    session = [manager GET:url parameters:params headers:@{} progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"{\n parameters: %@ url:   %@ \n responseObject:  %@ \n}",(params==nil?@"没有参数":params),url,responseObject);
        if ([responseObject[@"status"] isEqualToString:@"relogin"])
        {
            SKUserUserDefaults_Remove(@"UserInfo");
            [UserInfoSingleton shareInstance].userInfo =nil;
            SKPost_Notify(@"UserLogOut", nil, @{});
            [[CommonToolHelper shareInstance].currentVC.view makeToast:@"登录已失效，请重新登录" duration:1 position:CSToastPositionCenter];
            LoginViewController * loginVC =[[LoginViewController alloc] init];
            loginVC.myLoginResult = ^(id model) {
                if (reloginRefreshBlock) {
                    
                    reloginRefreshBlock(model);
                }
            };
            [[CommonToolHelper shareInstance].currentVC.navigationController pushViewController:loginVC animated:YES];
        }
        else
        {
            if (successBlock) successBlock(responseObject);
        }
        if ([[self allTasks] containsObject:session]) {
            [[self allTasks] removeObject:session];
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failBlock) failBlock(error);
        [[self allTasks] removeObject:session];
    }];
    //无论是否有旧请求，先执行取消旧请求，反正都需要刷新请求
    YQURLSessionTask *oldTask = [self cancleSameRequestInTasksPool:session];
    if (oldTask) [[self allTasks] removeObject:oldTask];
    if (session) [[self allTasks] addObject:session];
    [session resume];
    return session;
}

#pragma mark - post
+ (YQURLSessionTask *)postWithUrl:(NSString *)url
                   refreshRequest:(BOOL)refresh
                            cache:(BOOL)cache
                           params:(NSDictionary *)params
                    progressBlock:(YQPostProgress)progressBlock
                     successBlock:(YQResponseSuccessBlock)successBlock
                        failBlock:(YQResponseFailBlock)failBlock {
    __block YQURLSessionTask *session = nil;
    
    AFHTTPSessionManager *manager = [self manager];
    
    if (networkStatus == YQNetworkStatusNotReachable) {
        if (failBlock) failBlock(YQ_ERROR);
        return session;
    }
    
    id responseObj = [[YQCacheManager shareManager] getCacheResponseObjectWithRequestUrl:url params:params];
    
    if (responseObj && cache) {
        if (successBlock) successBlock(responseObj);
    }
    if (![url containsString:@"http"]) {
        
        url = [NSString stringWithFormat:@"%@%@",BASEURL,url];
    }
    session = [manager POST:url parameters:params headers:@{} progress:^(NSProgress * _Nonnull uploadProgress) {
        if (progressBlock) {
            progressBlock(uploadProgress.completedUnitCount, uploadProgress.totalUnitCount);
        }
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"{\n parameters: %@ url:   %@ \n responseObject:  %@ \n}",(params==nil?@"没有参数":params),url,responseObject);
        if (successBlock) successBlock(responseObject);
        if (cache) [[YQCacheManager shareManager] cacheResponseObject:responseObject requestUrl:url params:params];
        if ([[self allTasks] containsObject:session]) {
            [[self allTasks] removeObject:session];
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failBlock) failBlock(error);
        [[self allTasks] removeObject:session];
    }];
    if ([self haveSameRequestInTasksPool:session] && !refresh) {
        [session cancel];
        return session;
    }else {
        YQURLSessionTask *oldTask = [self cancleSameRequestInTasksPool:session];
        if (oldTask) [[self allTasks] removeObject:oldTask];
        if (session) [[self allTasks] addObject:session];
        [session resume];
        return session;
    }
}
+ (YQURLSessionTask *)postWithUrl:(NSString *)url
                           params:(NSDictionary *)params
              reloginRefreshBlock:(YQReloginRefreshBlock)reloginRefreshBlock
                     successBlock:(YQResponseSuccessBlock)successBlock
                        failBlock:(YQResponseFailBlock)failBlock {
    __block YQURLSessionTask *session = nil;
    
    AFHTTPSessionManager *manager = [self manager];
    
    if (networkStatus == YQNetworkStatusNotReachable) {
        if (failBlock) failBlock(YQ_ERROR);
        return session;
    }
        
    if (![url containsString:@"http"]) {
        
        url = [NSString stringWithFormat:@"%@%@",BASEURL,url];
    }
    session = [manager POST:url parameters:params headers:@{} progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"{\n parameters: %@ url:   %@ \n responseObject:  %@ \n}",(params==nil?@"没有参数":params),url,responseObject);
        if ([responseObject[@"status"] isEqualToString:@"relogin"]) {
            SKUserUserDefaults_Remove(@"UserInfo");
            [UserInfoSingleton shareInstance].userInfo =nil;
            SKPost_Notify(@"UserLogOut", nil, @{});
            [[CommonToolHelper shareInstance].currentVC.view makeToast:@"登录已失效，请重新登录" duration:1 position:CSToastPositionCenter];
            LoginViewController * loginVC =[[LoginViewController alloc] init];
            loginVC.myLoginResult = ^(id model) {
                if (reloginRefreshBlock) {
                    reloginRefreshBlock(model);
                }
            };
            [[CommonToolHelper shareInstance].currentVC.navigationController pushViewController:loginVC animated:YES];
        }else {
            if (successBlock) successBlock(responseObject);
        }
        if ([[self allTasks] containsObject:session]) {
            [[self allTasks] removeObject:session];
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failBlock) failBlock(error);
        [[self allTasks] removeObject:session];
    }];
    YQURLSessionTask *oldTask = [self cancleSameRequestInTasksPool:session];
    if (oldTask) [[self allTasks] removeObject:oldTask];
    if (session) [[self allTasks] addObject:session];
    [session resume];
    return session;
}

// 上传多张图片
+ (YQURLSessionTask *)updateFilesWithUrl:(NSString *)url
                              parameters:(NSDictionary*)parameters
                               fileDatas:(NSArray <NSData *>*)datas
                                    type:(NSString *)type
                                   names:(NSArray <NSString *>*)names
                                mimeType:(NSString *)mimeType
                           progressBlock:(YQUploadProgressBlock)progressBlock
                            successBlock:(YQResponseSuccessBlock)successBlock
                               failBlock:(YQResponseFailBlock)failBlock {
    __block YQURLSessionTask *session = nil;
    
    AFHTTPSessionManager *manager = [self manager];
    
    if (networkStatus == YQNetworkStatusNotReachable) {
        if (failBlock) failBlock(YQ_ERROR);
        return session;
    }
    if (![url containsString:@"http"]) {
        
        url = [NSString stringWithFormat:@"%@%@",BASEURL,url];
    }
    session = [manager POST:url parameters:parameters headers:@{} constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        for (int i = 0; i < datas.count; i++) {
            NSData *data = datas[i];
            NSString *name = names[i];
            NSString *fileName = nil;
            NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
            formatter.dateFormat = @"yyyyMMddHHmmss";
            NSString *day = [formatter stringFromDate:[NSDate date]];
            fileName = [NSString stringWithFormat:@"%@.%@",day,type];
            [formData appendPartWithFileData:data name:name fileName:fileName mimeType:mimeType];
        }
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        if (progressBlock) progressBlock (uploadProgress.completedUnitCount,uploadProgress.totalUnitCount);
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"{\n parameters: %@ url:   %@ \n responseObject:  %@ \n}",(parameters==nil?@"没有参数":parameters),url,responseObject);
        if (successBlock) successBlock(responseObject);
        [[self allTasks] removeObject:session];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failBlock) failBlock(error);
        [[self allTasks] removeObject:session];
    }];
    
    [session resume];
    if (session) [[self allTasks] addObject:session];
    return session;
}
#pragma mark - 文件上传
+ (YQURLSessionTask *)uploadFileWithUrl:(NSString *)url
                             parameters:(NSDictionary*)parameters
                               fileData:(NSData *)data
                                   type:(NSString *)type
                                   name:(NSString *)name
                               mimeType:(NSString *)mimeType
                          progressBlock:(YQUploadProgressBlock)progressBlock
                           successBlock:(YQResponseSuccessBlock)successBlock
                              failBlock:(YQResponseFailBlock)failBlock {
    __block YQURLSessionTask *session = nil;
    
    AFHTTPSessionManager *manager = [self manager];
    
    if (networkStatus == YQNetworkStatusNotReachable) {
        if (failBlock) failBlock(YQ_ERROR);
        return session;
    }
    if (![url containsString:@"http"]) {
        url = [NSString stringWithFormat:@"%@%@",BASEURL,url];
    }
    session = [manager POST:url parameters:parameters headers:@{} constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        NSString *fileName = nil;
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        formatter.dateFormat = @"yyyyMMddHHmmss";
        NSString *day = [formatter stringFromDate:[NSDate date]];
        fileName = [NSString stringWithFormat:@"%@.%@",day,type];
        [formData appendPartWithFileData:data name:name fileName:fileName mimeType:mimeType];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        if (progressBlock) progressBlock (uploadProgress.completedUnitCount,uploadProgress.totalUnitCount);
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"{\n parameters: %@ url:   %@ \n responseObject:  %@ \n}",(parameters==nil?@"没有参数":parameters),url,responseObject);
        if (successBlock) successBlock(responseObject);
        [[self allTasks] removeObject:session];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failBlock) failBlock(error);
        [[self allTasks] removeObject:session];
    }];
    [session resume];
    if (session) [[self allTasks] addObject:session];
    return session;
}
+ (YQURLSessionTask *)uploadFileWithUrl:(NSString *)url
                             parameters:(NSDictionary*)parameters
                               fileData:(NSData *)data
                                   type:(NSString *)type
                                   name:(NSString *)name
                               mimeType:(NSString *)mimeType
                    reloginRefreshBlock:(YQReloginRefreshBlock)reloginRefreshBlock
                           successBlock:(YQResponseSuccessBlock)successBlock
                              failBlock:(YQResponseFailBlock)failBlock {
    __block YQURLSessionTask *session = nil;
    
    AFHTTPSessionManager *manager = [self manager];
    
    if (networkStatus == YQNetworkStatusNotReachable) {
        if (failBlock) failBlock(YQ_ERROR);
        return session;
    }
    if (![url containsString:@"http"]) {
        url = [NSString stringWithFormat:@"%@%@",BASEURL,url];
    }
    session = [manager POST:url parameters:parameters headers:@{} constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        NSString *fileName = nil;
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        formatter.dateFormat = @"yyyyMMddHHmmss";
        NSString *day = [formatter stringFromDate:[NSDate date]];
        fileName = [NSString stringWithFormat:@"%@.%@",day,type];
        [formData appendPartWithFileData:data name:name fileName:fileName mimeType:mimeType];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"{\n parameters: %@ url:   %@ \n responseObject:  %@ \n}",(parameters==nil?@"没有参数":parameters),url,responseObject);
        if ([responseObject[@"status"] isEqualToString:@"relogin"])
        {
            SKUserUserDefaults_Remove(@"UserInfo");
            [UserInfoSingleton shareInstance].userInfo =nil;
            
            SKPost_Notify(@"UserLogOut", nil, @{});
            [[CommonToolHelper shareInstance].currentVC.view makeToast:@"登录已失效，请重新登录" duration:1 position:CSToastPositionCenter];
            LoginViewController * loginVC =[[LoginViewController alloc] init];
            loginVC.myLoginResult = ^(id model) {
                if (reloginRefreshBlock) {
                    reloginRefreshBlock(model);
                }
            };
            [[CommonToolHelper shareInstance].currentVC.navigationController pushViewController:loginVC animated:YES];
        }
        else
        {
            if (successBlock) successBlock(responseObject);
        }
        [[self allTasks] removeObject:session];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failBlock) failBlock(error);
        [[self allTasks] removeObject:session];
    }];
    [session resume];
    
    if (session) [[self allTasks] addObject:session];
    
    return session;
}

#pragma mark - 多文件上传
+ (NSArray *)uploadMultFileWithUrl:(NSString *)url
                        parameters:(NSDictionary*)parameters
                         fileDatas:(NSArray *)datas
                              type:(NSString *)type
                              name:(NSString *)name
                          mimeType:(NSString *)mimeTypes
                     progressBlock:(YQUploadProgressBlock)progressBlock
                      successBlock:(YQMultUploadSuccessBlock)successBlock
                         failBlock:(YQMultUploadFailBlock)failBlock {
    
    if (networkStatus == YQNetworkStatusNotReachable) {
        if (failBlock) failBlock(@[YQ_ERROR]);
        return nil;
    }
    
    __block NSMutableArray *sessions = [NSMutableArray array];
    __block NSMutableArray *responses = [NSMutableArray array];
    __block NSMutableArray *failResponse = [NSMutableArray array];
    
    dispatch_group_t uploadGroup = dispatch_group_create();
    if (![url containsString:@"http"]) {
        
        url = [NSString stringWithFormat:@"%@%@",BASEURL,url];
    }
    NSInteger count = datas.count;
    for (int i = 0; i < count; i++) {
        __block YQURLSessionTask *session = nil;
        
        dispatch_group_enter(uploadGroup);
        
        session = [self uploadFileWithUrl:url
                               parameters:parameters
                                 fileData:datas[i]
                                     type:type name:name
                                 mimeType:mimeTypes
                            progressBlock:^(int64_t bytesWritten, int64_t totalBytes) {
                                if (progressBlock) progressBlock(bytesWritten,
                                                                 totalBytes);
                                
                            } successBlock:^(id response) {
                                [responses addObject:response];
                                
                                dispatch_group_leave(uploadGroup);
                                
                                [sessions removeObject:session];
                                
                            } failBlock:^(NSError *error) {
                                NSError *Error = [NSError errorWithDomain:url code:-999 userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"第%d次上传失败",i]}];
                                
                                [failResponse addObject:Error];
                                
                                dispatch_group_leave(uploadGroup);
                                
                                [sessions removeObject:session];
                            }];
        
        [session resume];
        
        if (session) [sessions addObject:session];
    }
    
    [[self allTasks] addObjectsFromArray:sessions];
    
    dispatch_group_notify(uploadGroup, dispatch_get_main_queue(), ^{
        if (responses.count > 0) {
            if (successBlock) {
                successBlock([responses copy]);
                if (sessions.count > 0) {
                    [[self allTasks] removeObjectsInArray:sessions];
                }
            }
        }
        
        if (failResponse.count > 0) {
            if (failBlock) {
                failBlock([failResponse copy]);
                if (sessions.count > 0) {
                    [[self allTasks] removeObjectsInArray:sessions];
                }
            }
        }
        
    });
    
    return [sessions copy];
}

/// 上传文件
/// @param url url
/// @param param param
/// @param files files
/// @param successBlock 成功
/// @param failBlock 失败
+ (void)uploadFilesWithUrl:(NSString *)url
                     Param:(NSDictionary *)param
                     Files:(NSArray <NSDictionary<NSString *, NSString *> *>*)files
              successBlock:(YQResponseSuccessBlock)successBlock
                 failBlock:(YQResponseFailBlock)failBlock {
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    
    NSMutableString *baseUrl = [NSMutableString stringWithFormat:@"%@%@", BASEURL, url];
    if (param.allKeys.count) {
        [baseUrl appendString:@"?"];
    }
    for (NSString *key in param.allKeys) {
        [baseUrl appendFormat:@"%@=%@", key, [param valueForKey:key]];
        [baseUrl appendString:@"&"];
    }
    if ([baseUrl containsString:@"&"]) {
        [baseUrl deleteCharactersInRange:NSMakeRange(baseUrl.length - 1, 1)]; }
    
    
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:baseUrl]
      cachePolicy:NSURLRequestUseProtocolCachePolicy
      timeoutInterval:10.0];
    
    NSMutableArray *mArr = [NSMutableArray arrayWithCapacity:files.count];
    
    for (NSDictionary *fileInfo in files) {
        [mArr addObject:@{@"name":fileInfo.allKeys.lastObject,
                          @"fileName":fileInfo.allValues.lastObject,
                          @"contentType":@"png"
        }];
    }
    NSArray *parameters = mArr;
    NSString *boundary = @"----WebKitFormBoundary7MA4YWxkTrZu0gW";
    NSError *error;
    NSMutableString *body = [NSMutableString string];

    for (NSDictionary *param in parameters) {
      [body appendFormat:@"--%@\r\n", boundary];
      if (param[@"fileName"]) {
          [body appendFormat:@"Content-Disposition:form-data; name=\"%@\"; filename=\"%@\"\r\n", param[@"name"], param[@"fileName"]];
          [body appendFormat:@"Content-Type: %@\r\n\r\n", param[@"contentType"]];
          NSData *data = [NSData dataWithContentsOfFile:param[@"fileName"]];
          [body appendFormat:@"%@", [data base64EncodedStringWithOptions:0]];
          if (error) {
              NSLog(@"%@", error);
          }
      } else {
          [body appendFormat:@"Content-Disposition:form-data; name=\"%@\"\r\n\r\n", param[@"name"]];
          [body appendFormat:@"%@", param[@"value"]];
      }
    }
    [body appendFormat:@"\r\n--%@--\r\n", boundary];
    NSData *postData = [body dataUsingEncoding:NSUTF8StringEncoding];
    [request setHTTPBody:postData];

    [request setHTTPMethod:@"POST"];

    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
    completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
      if (error) {
          if (failBlock) {
              failBlock(error);
          }
      } else {
          NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
          NSError *parseError = nil;
          NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
          if (successBlock) {
              successBlock(responseDictionary);
          }
          dispatch_semaphore_signal(sema);
      }
    }];
    [dataTask resume];
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
#pragma mark - 下载
+ (YQURLSessionTask *)downloadWithUrl:(NSString *)url
                        progressBlock:(YQDownloadProgress)progressBlock
                         successBlock:(YQDownloadSuccessBlock)successBlock
                            failBlock:(YQDownloadFailBlock)failBlock {
    NSString *type = nil;
    NSArray *subStringArr = nil;
    __block YQURLSessionTask *session = nil;
    
    NSURL *fileUrl = [[YQCacheManager shareManager] getDownloadDataFromCacheWithRequestUrl:url];
    
    if (fileUrl) {
        if (successBlock) successBlock(fileUrl);
        return nil;
    }
    
    if (url) {
        subStringArr = [url componentsSeparatedByString:@"."];
        if (subStringArr.count > 0) {
            type = subStringArr[subStringArr.count - 1];
        }
    }
    AFHTTPSessionManager *manager = [self manager];
    //响应内容序列化为二进制
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    session = [manager GET:url parameters:nil headers:@{} progress:^(NSProgress * _Nonnull downloadProgress) {
        if (progressBlock) progressBlock(downloadProgress.completedUnitCount, downloadProgress.totalUnitCount);
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (successBlock) {
            NSData *dataObj = (NSData *)responseObject;
            [[YQCacheManager shareManager] storeDownloadData:dataObj requestUrl:url];
            NSURL *downFileUrl = [[YQCacheManager shareManager] getDownloadDataFromCacheWithRequestUrl:url];
            successBlock(downFileUrl);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failBlock) {
            failBlock (error); }
    }];
    [session resume];
    if (session) [[self allTasks] addObject:session];
    return session;
}

#pragma mark - other method
+ (void)setupTimeout:(NSTimeInterval)timeout {
    requestTimeout = timeout;
}

+ (void)cancleAllRequest {
    @synchronized (self) {
        [[self allTasks] enumerateObjectsUsingBlock:^(YQURLSessionTask  *_Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([obj isKindOfClass:[YQURLSessionTask class]]) {
                [obj cancel];
            }
        }];
        [[self allTasks] removeAllObjects];
    }
}

+ (void)cancelRequestWithURL:(NSString *)url {
    if (!url) return;
    
    
    if (![url containsString:@"http"]) {
        
        url = [NSString stringWithFormat:@"%@%@",BASEURL,url];
        
    }
    @synchronized (self) {
        [[self allTasks] enumerateObjectsUsingBlock:^(YQURLSessionTask * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([obj isKindOfClass:[YQURLSessionTask class]]) {
                if ([obj.currentRequest.URL.absoluteString hasSuffix:url]) {
                    [obj cancel];
                    *stop = YES;
                }
            }
        }];
    }
}

+ (void)configHttpHeader:(NSDictionary *)httpHeader {
    headers = httpHeader;
}

+ (NSArray *)currentRunningTasks {
    return [[self allTasks] copy];
}

@end

@implementation YQNetworking (cache)
+ (NSUInteger)totalCacheSize {
    return [[YQCacheManager shareManager] totalCacheSize];
}

+ (NSUInteger)totalDownloadDataSize {
    return [[YQCacheManager shareManager] totalDownloadDataSize];
}

+ (void)clearDownloadData {
    [[YQCacheManager shareManager] clearDownloadData];
}

+ (NSString *)getDownDirectoryPath {
    return [[YQCacheManager shareManager] getDownDirectoryPath];
}

+ (NSString *)getCacheDiretoryPath {
    
    return [[YQCacheManager shareManager] getCacheDiretoryPath];
}

+ (void)clearTotalCache {
    [[YQCacheManager shareManager] clearTotalCache];
}

@end
